/*-------------------------------------------------------------------------
 *
 * psqlscan.h
 *	  SQL命令的词法扫描器
 *
 * 此词法分析器曾经是psql的一部分，这种遗产反映在文件名以及函数和typedef名称中，
 * 尽管现在它也可以被其他前端程序使用。 还可以使用兼容的附加词法分析器扩展
 * 此词法分析器以处理特定程序的反斜杠命令。
 *
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/fe_utils/psqlscan.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef PSQLSCAN_H
#define PSQLSCAN_H

#include "pqexpbuffer.h"


/* 词法分析器内部状态的抽象类型 */
typedef struct PsqlScanStateData *PsqlScanState;

/* psql_scan() 的终止状态 */
typedef enum
{
	PSCAN_SEMICOLON,			/* 找到命令结束的分号 */
	PSCAN_BACKSLASH,			/* 找到反斜杠命令 */
	PSCAN_INCOMPLETE,			/* 行尾，SQL 语句不完整 */
	PSCAN_EOL					/* 行尾，SQL 可能完整 */
} PsqlScanResult;

/* psql_scan() 返回的提示类型 */
typedef enum _promptStatus
{
	PROMPT_READY,
	PROMPT_CONTINUE,
	PROMPT_COMMENT,
	PROMPT_SINGLEQUOTE,
	PROMPT_DOUBLEQUOTE,
	PROMPT_DOLLARQUOTE,
	PROMPT_PAREN,
	PROMPT_COPY
} promptStatus_t;

/* 引用 get_variable() 回调的请求类型 */
typedef enum
{
	PQUOTE_PLAIN,				/* 仅返回实际值 */
	PQUOTE_SQL_LITERAL,			/* 添加引号以使其成为有效的 SQL 字面量 */
	PQUOTE_SQL_IDENT,			/* 如果需要，引号以生成 SQL 标识符 */
	PQUOTE_SHELL_ARG			/* 如果需要，引号以确保在 shell 命令中安全 */
} PsqlScanQuoteType;

/* 供分析器使用的回调函数 */
typedef struct PsqlScanCallbacks
{
	/* 获取变量的值，作为可释放的字符串；如果未知则为 NULL */
	/* 如果不需要变量替换，此指针可以为 NULL */
	char	   *(*get_variable) (const char *varname, PsqlScanQuoteType quote,
								 void *passthrough);
} PsqlScanCallbacks;


extern PsqlScanState psql_scan_create(const PsqlScanCallbacks *callbacks);
extern void psql_scan_destroy(PsqlScanState state);

extern void psql_scan_set_passthrough(PsqlScanState state, void *passthrough);

extern void psql_scan_setup(PsqlScanState state,
							const char *line, int line_len,
							int encoding, bool std_strings);
extern void psql_scan_finish(PsqlScanState state);

extern PsqlScanResult psql_scan(PsqlScanState state,
								PQExpBuffer query_buf,
								promptStatus_t *prompt);

extern void psql_scan_reset(PsqlScanState state);

extern void psql_scan_reselect_sql_lexer(PsqlScanState state);

extern bool psql_scan_in_quote(PsqlScanState state);

#endif							/* PSQLSCAN_H */
